
#include "btl_config.h"
#include "fp_flash.h"
#include "fp_log.h"
#include "protocol.h"
#include "fp_timer.h"

struct fp_flash_info g_fp_flash_info = {0};
struct fp_flash_info* fp_flash(void)
{
    return &g_fp_flash_info;
}

unsigned int align2sector(unsigned int size)
{
    unsigned int count = (size / FLASH_SECTOR_SIZE);
    unsigned int offset = (size % FLASH_SECTOR_SIZE);
    unsigned int total = size;

    if (offset)
        total = (count + 1) * FLASH_SECTOR_SIZE;

    return total;
}

SDFILE *fp_flash_init(void)
{
    struct fp_flash_info *info = fp_flash();
    if (info->fp_handle)
        return info->fp_handle;

    info->fp_handle = fopen(FP_FLASH_DIR, "r+w");
    if (info->fp_handle == NULL)
    {
        bf_print_d("open fail!!!");
        return NULL;
    }

    fget_attrs(info->fp_handle, &(info->attr));

    info->addr.vfs_start_addr = info->attr.sclust;

    unsigned int flash_addr = sdfile_cpu_addr2flash_addr(info->attr.sclust);
    bf_print_d("[cpu_addr:0x%x, flash_addr:0x%x, fsize:%d kb]", info->attr.sclust, flash_addr, ((info->attr.fsize) / 1024));
    return info->fp_handle;
}

int fp_flash_erase(unsigned int addr, unsigned int size)
{
    struct fp_flash_info *info = fp_flash();
    unsigned int erase_total_size = align2sector(size);
    unsigned int vfs_addr = info->addr.vfs_start_addr + addr;
    unsigned int erase_addr = sdfile_cpu_addr2flash_addr(vfs_addr);
    unsigned int erase_size = 4096;
    unsigned int erase_cmd = SECTOR_ERASER;

    // DEBUG("%s[0x%x %dK]", __func__, erase_addr, erase_total_size / 1024);
    // DEBUG("%s 64K align:%s", __func__, erase_addr % 0x10000 ? "flase" : "true");
    // DEBUG("%s 4K align:%s", __func__, erase_addr % 0x1000 ? "flase" : "true");

    while (erase_total_size)
    {
        clr_wdt();
        // DEBUG("==================== >>>>> ADDR 0x%x", erase_addr);
        sfc_erase(erase_cmd, erase_addr);
        erase_addr += erase_size;
        erase_total_size -= erase_size;
    }

    return 0;
}

int fp_flash_write(unsigned int addr, const unsigned char *data, unsigned int len)
{
    int retval = -1;
    SDFILE *fd = NULL;

    /* Create a File with O_CREAT */
    fd = fp_flash_init();
    if (fd == NULL)
    {
        bf_print_d("open fail!!!");
        return -1;
    }

    fp_flash_erase(addr, len);

    fseek(fd, addr, SEEK_SET);
    retval = fwrite(fd, (void *)data, len);
    if (retval == len)
        retval = 0;

    bf_print_d("retval = %d", retval);
    // fclose(fd);
    return retval;
}

int fp_flash_read(unsigned int addr, unsigned int size, unsigned char *buf)
{
    int retval = -1;
    int bytes = 0;
    SDFILE *fd = NULL;

    fd = fp_flash_init();
    if (fd == NULL)
    {
        bf_print_d("open fail!!!");
        return -1;
    }

    fseek(fd, addr, SEEK_SET);
    bytes = fread(fd, (char *)buf, size);

    if (bytes == size)
        retval = 0;

    // fclose(fd);
    return retval;
}

int fp_flash_is_xip_accessible(unsigned int flash_addr, unsigned int len)
{
    (void)flash_addr;
    (void)len;
    return 0;
}
